package utils

import (
	"errors"
	"gitee.com/fierce_wolf/gos7"
	"regexp"
	"strconv"
	"strings"
)

type s7Addr struct {
	Area     string
	DBNumber int
	ByteAddr int
	BitAddr  int
}

func (e *s7Addr) ParseS7Addr(addr string) (*s7Addr, error) {
	addr = strings.ToUpper(addr)

	// 根据.分拆
	items := strings.Split(addr, ".")
	if len(items) < 1 {
		return nil, errors.New("地址格式非法")
	}

	// 区域：是否为DB1或者Q这样的格式
	if !regexp.MustCompile(`^[A-Za-z].*\d$`).MatchString(items[0]) && !regexp.MustCompile(`^[A-Za-z]+$`).MatchString(items[0]) {
		return nil, errors.New("不是合法的区域格式，正确的范例为DB1.1.2")
	}
	// 检查：是否为数字
	for i := 1; i < len(items); i++ {
		if !regexp.MustCompile(`^\d+$`).MatchString(items[i]) {
			return nil, errors.New("不是合法的地址格式，正确的范例为DB1.1.2")
		}
	}

	s7addr := &s7Addr{
		Area:     "",
		DBNumber: -1,
		ByteAddr: -1,
		BitAddr:  -1,
	}

	// area格式1：DB1
	if regexp.MustCompile(`^[A-Za-z].*\d$`).MatchString(items[0]) {
		// 正则表达式匹配非数字字符后面的数字
		match := regexp.MustCompile(`[^0-9]*[0-9]`).FindStringIndex(items[0])
		if match != nil && len(match) == 2 {
			s7addr.Area = items[0][match[0] : match[1]-1]
			val, err := strconv.ParseInt(items[0][match[1]-1:], 10, 16)
			if err != nil {
				return nil, err
			}
			s7addr.DBNumber = int(val)
		}
	}
	// area格式2：DB
	if regexp.MustCompile(`^[A-Za-z]+$`).MatchString(items[0]) {
		s7addr.Area = items[0]
	}

	// 字节地址
	if len(items) > 1 {
		val, err := strconv.ParseInt(items[1], 10, 16)
		if err != nil {
			return nil, err
		}
		s7addr.ByteAddr = int(val)
	}

	// 字节地址
	if len(items) > 2 {
		val, err := strconv.ParseInt(items[2], 10, 16)
		if err != nil {
			return nil, err
		}
		s7addr.BitAddr = int(val)
	}

	return s7addr, nil
}

func (e *s7Addr) GetS7AddrCode() (int, error) {
	switch e.Area {
	case "DB":
		return gos7.S7AreaDB, nil
	case "TM":
		return gos7.S7AreaTM, nil
	case "CT":
		return gos7.S7AreaCT, nil
	case "EB":
		return gos7.S7AreaPE, nil
	case "PA":
		return gos7.S7AreaPE, nil
	case "MK":
		return gos7.S7AreaMK, nil
	default:
		return 0, errors.New("不支持的区域")
	}
}
